package org.linloong.modules.apis.monitor.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Hidden;
import lombok.RequiredArgsConstructor;
import org.linloong.modules.apis.monitor.entity.*;
import org.linloong.modules.apis.monitor.mapper.DeviceInfoMapper;
import org.linloong.modules.apis.monitor.sync.SensorDataParser;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
@Hidden // Swagger隐藏服务层，仅暴露Controller层
public class RealTimeDataService {
    private final WebClient monitorWebClient;
    private final SensorDataParser dataParser; // 注入解析工具类
    private final DeviceInfoMapper deviceInfoMapper; // 用于查询设备layout

    // -------------------------- 设备信息接口（文档"气象设备接口"章节） --------------------------
    /**
     * 获取设备信息（文档"气象设备接口"：GET /api/Deviceinfoes('{deviceId}')）
     */
    public Mono<DeviceInfo> getDeviceInfo(String deviceId) {
        String uri = String.format("/api/Deviceinfoes('%s')", deviceId);
        Mono<DeviceInfo> deviceInfoMono = monitorWebClient.get().uri(uri).retrieve().bodyToMono(DeviceInfo.class);
        DeviceInfo deviceInfo = deviceInfoMono.block();
        if (deviceInfo != null) {
            boolean exists = deviceInfoMapper.exists(new LambdaQueryWrapper<DeviceInfo>()
                    .eq(DeviceInfo::getDeviceId, deviceId));
            if (!exists) {
                deviceInfoMapper.insert(deviceInfo);
            }
        }
        return deviceInfoMono;
    }
    /**
     * 获取最新气象数据并解析
     */
    public Mono<List<WeatherDataParsed>> getLatestWeatherDataParsed(String deviceId) {
        // 1. 获取设备layout
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(
                new LambdaQueryWrapper<DeviceInfo>().eq(DeviceInfo::getDeviceId, deviceId)
        );
        if (deviceInfo == null || deviceInfo.getLayout() == null) {
            return Mono.just(List.of()); // 无layout返回空列表
        }

        // 2. 获取原始数据并解析
        String uri = String.format("/api/devicedatas('%s')/Current", deviceId);
        return monitorWebClient.get().uri(uri)
                .retrieve()
                .bodyToMono(WeatherData.class)
                .doOnNext(data -> {
                    data.setApiId(data.getId());
                    data.setCreateTime(LocalDateTime.now()); // 补充入库时间
                })
                .map(rawData ->
                        // 调用解析工具类生成解析结果
                        dataParser.parse(
                                rawData.getId(),
                                rawData.getDeviceId(),
                                rawData.getTimestamp(),
                                rawData.getDataArray(),
                                deviceInfo.getLayout()
                        )
                );
    }
    // -------------------------- 气象数据接口（文档"气象数据接口"章节） --------------------------
    /**
     * 获取气象设备最新一条数据（文档"气象数据接口"：GET /api/devicedatas('{deviceId}')/Current）
     */
    public Mono<WeatherData> getLatestWeatherData(String deviceId) {
        String uri = String.format("/api/devicedatas('%s')/Current", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(WeatherData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取气象设备时间范围数据（文档要求用$filter，对应：GET /api/devicedatas('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<WeatherData>> getWeatherDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/devicedatas('%s')?%s", deviceId, filter);
        return getApiResponse(uri, WeatherData.class);
    }

    // -------------------------- 物候接口（文档"物候接口"章节） --------------------------
    /**
     * 获取物候设备最新一条数据（文档"物候接口"：GET /api/PhenologyData('{deviceId}')/Current()）
     */
    public Mono<PhenologyData> getLatestPhenologyData(String deviceId) {
        String uri = String.format("/api/PhenologyData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(PhenologyData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取物候设备时间范围数据（文档要求用$filter，对应：GET /api/PhenologyData('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<PhenologyData>> getPhenologyDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/PhenologyData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, PhenologyData.class);
    }

    // -------------------------- 盖度接口（文档"盖度接口"章节） --------------------------
    /**
     * 获取盖度设备最新一条数据（文档"盖度接口"：GET /api/CoverageData('{deviceId}')/Current()）
     */
    public Mono<CoverageData> getLatestCoverageData(String deviceId) {
        String uri = String.format("/api/CoverageData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(CoverageData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取盖度设备时间范围数据（文档要求用$filter，对应：GET /api/CoverageData('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<CoverageData>> getCoverageDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/CoverageData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, CoverageData.class);
    }

    // -------------------------- 盖度+接口（文档"盖度+接口"章节，2.7版本新增） --------------------------
    /**
     * 获取盖度+设备最新一条数据（文档"盖度+接口"：GET /api/CoveragePlusData('{deviceId}')/Current()）
     */
    public Mono<CoveragePlusData> getLatestCoveragePlusData(String deviceId) {
        String uri = String.format("/api/CoveragePlusData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(CoveragePlusData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取盖度+设备时间范围数据（文档要求用$filter，对应：GET /api/CoveragePlusData('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<CoveragePlusData>> getCoveragePlusDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/CoveragePlusData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, CoveragePlusData.class);
    }

    // -------------------------- 光谱物候接口（文档"光谱物候接口"章节，2.3版本新增） --------------------------
    /**
     * 获取光谱物候设备最新一条数据（文档"光谱物候接口"：GET /api/SpectrumData('{deviceId}')/Current()）
     */
    public Mono<SpectrumData> getLatestSpectrumData(String deviceId) {
        String uri = String.format("/api/SpectrumData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(SpectrumData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取光谱物候设备时间范围数据（文档要求用$filter，对应：GET /api/SpectrumData('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<SpectrumData>> getSpectrumDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/SpectrumData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, SpectrumData.class);
    }

    // -------------------------- 物候+接口（文档"物候+接口"章节，2.5版本新增） --------------------------
    /**
     * 获取物候+设备最新一条数据（文档"物候+接口"：GET /api/PhenologyPlusData('{deviceId}')/Current()）
     */
    public Mono<PhenologyPlusData> getLatestPhenologyPlusData(String deviceId) {
        String uri = String.format("/api/PhenologyPlusData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(PhenologyPlusData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取物候+设备时间范围数据）
     */
    public Mono<ApiResponse<PhenologyPlusData>> getPhenologyPlusDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/PhenologyPlusData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, PhenologyPlusData.class);
    }

    // -------------------------- 虫情灯接口（文档"虫情灯数据接口"章节） --------------------------
    /**
     * 获取虫情灯设备最新一条数据（文档"虫情灯数据接口"：GET /api/InsectData('{deviceId}')/Current()）
     */
    public Mono<InsectData> getLatestInsectData(String deviceId) {
        String uri = String.format("/api/InsectData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(InsectData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取虫情灯设备时间范围数据（文档要求用$filter，对应：GET /api/InsectData('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<InsectData>> getInsectDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/InsectData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, InsectData.class);
    }

    // -------------------------- 声纹接口（文档"声纹数据接口"章节，2.6版本新增） --------------------------
    /**
     * 获取声纹设备最新一条数据（文档"声纹数据接口"：GET /api/AudioPatternData('{deviceId}')/Current()）
     */
    public Mono<AudioPatternData> getLatestAudioPatternData(String deviceId) {
        String uri = String.format("/api/AudioPatternData('%s')/Current()", deviceId);
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono(AudioPatternData.class)
                .doOnNext(data -> data.setApiId(data.getId()));
    }

    /**
     * 获取声纹设备时间范围数据（文档要求用$filter，对应：GET /api/AudioPatternData('{deviceId}')?$filter=...）
     */
    public Mono<ApiResponse<AudioPatternData>> getAudioPatternDataByTimeRange(String deviceId, Long startTs, Long endTs) {
        String filter = String.format("$filter=(Timestamp ge %d) and (Timestamp le %d)", startTs, endTs);
        String uri = String.format("/api/AudioPatternData('%s')?%s", deviceId, filter);
        return getApiResponse(uri, AudioPatternData.class);
    }

    // -------------------------- 通用方法（获取ApiResponse） --------------------------
    private <T> Mono<ApiResponse<T>> getApiResponse(String uri, Class<T> clazz) {
        Type type = new ParameterizedType() {
            @Override
            public Type[] getActualTypeArguments() {
                return new Type[]{clazz};
            }

            @Override
            public Type getRawType() {
                return ApiResponse.class;
            }

            @Override
            public Type getOwnerType() {
                return null;
            }
        };
        return monitorWebClient.get().uri(uri).retrieve().bodyToMono((Class<ApiResponse<T>>) type);
    }
}